package com.cmc.cloud.cmclink.doc.rpcservice.impl;

import java.util.*;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.cmc.cloud.cmclink.bdt.api.base.PartnerDataApi;
import com.cmc.cloud.cmclink.bdt.api.base.dto.resp.PartnerDataRespDTO;
import com.cmc.cloud.cmclink.bdt.api.base.dto.resp.PartnerListByCodeReqDTO;
import com.cmc.cloud.cmclink.doc.rpcservice.vo.AgentNameBaseVo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.alibaba.cloud.commons.lang.StringUtils;
import com.cmc.cloud.cmclink.bdt.api.base.VesselDataApi;
import com.cmc.cloud.cmclink.bdt.api.base.dto.req.VesselNameListByCodeReqDTO;
import com.cmc.cloud.cmclink.bdt.api.base.dto.resp.VesselNameDataRespDTO;
import com.cmc.cloud.cmclink.csm.api.base.CompanyInfoApi;
import com.cmc.cloud.cmclink.csm.api.base.CustomerInfoApi;
import com.cmc.cloud.cmclink.csm.api.base.dto.req.CompanyNameCastReqVO;
import com.cmc.cloud.cmclink.csm.api.base.dto.req.CustomerInfoReqVO;
import com.cmc.cloud.cmclink.csm.api.base.dto.resp.CompanyNameCastRespDTO;
import com.cmc.cloud.cmclink.csm.api.base.dto.resp.CustomerInfoRespDTO;
import com.cmc.cloud.cmclink.csm.api.base.enums.DataTypeEnum;
import com.cmc.cloud.cmclink.doc.constants.CommonConstants;
import com.cmc.cloud.cmclink.doc.constants.errorconstant.ApiErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.rpcservice.CustomerRpcService;
import com.cmc.cloud.cmclink.doc.rpcservice.constants.RpcErrorCodeConstants;
import com.cmc.cloud.cmclink.doc.rpcservice.vo.BkpNameBaseVo;
import com.cmc.cloud.cmclink.doc.vo.vesseloffhiremaintenancevo.VesselOffHireMaintenanceRespVO;
import com.cmes.framework.common.exception.util.ServiceExceptionUtil;
import com.cmes.framework.common.pojo.CommonResult;
import com.cmes.framework.ex.Assertion;

import cn.hutool.core.collection.CollectionUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * code name 转换
 *
 * @author 招商轮船-管理员
 */
@Service
@Validated
@Slf4j
public class CustomerRpcServiceImpl implements CustomerRpcService {

    @Resource
    private CompanyInfoApi companyInfoApi;

    @Resource
    private CustomerInfoApi customerInfoApi;

    @Resource
    private VesselDataApi vesselDataApi;

    @Resource
    private PartnerDataApi partnerDataApi;

    @Override
    public List<String> addQuery(String keyWord, DataTypeEnum typeEnum) {
        CustomerInfoReqVO companyInfoReqVO = new CustomerInfoReqVO();
        companyInfoReqVO.setKeyWord(keyWord);
        CommonResult<List<CustomerInfoRespDTO>> listCommonResult = customerInfoApi.customerInfoSelect(companyInfoReqVO);
        if (listCommonResult != null && CollectionUtil.isNotEmpty(listCommonResult.getCheckedData())) {
            List<String> codeList =
                listCommonResult.getData().stream().map(CustomerInfoRespDTO::getCsmCode).collect(Collectors.toList());
            return codeList;
        }
        return Collections.emptyList();
    }

    @Override
    public void fillName(List<? extends BkpNameBaseVo> list) {
        List<String> bkpCodeList = list.stream().map(BkpNameBaseVo::getBkpCode).collect(Collectors.toList());
        CompanyNameCastReqVO companyNameCastReqVO = new CompanyNameCastReqVO();
        companyNameCastReqVO.setCsmCodeList(bkpCodeList);
        CommonResult<List<CompanyNameCastRespDTO>> listCommonResult = null;
        try {
            listCommonResult = companyInfoApi.companyNameCast(companyNameCastReqVO);
        } catch (Exception e) {
            throw ServiceExceptionUtil.exception(RpcErrorCodeConstants.CUSTOMER_GET_ERROR);
        }
        Map<String, String> cnMap =
            listCommonResult.getCheckedData().stream().collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode,
                CompanyNameCastRespDTO::getCompanyNameLocal, (first, second) -> first));
        Map<String, String> enMap =
            listCommonResult.getCheckedData().stream().collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode,
                CompanyNameCastRespDTO::getCompanyNameEn, (first, second) -> first));
        list.forEach(vo -> {
            vo.setCompanyNameEn(enMap.get(vo.getBkpCode()));
            vo.setCompanyNameLocal(cnMap.get(vo.getBkpCode()));
        });
    }

    @Override
    public void fillAgentName(List<? extends AgentNameBaseVo> list) {
        List<String> agentCodeList = list.stream().map(AgentNameBaseVo::getAgentCode).collect(Collectors.toList());
        CompanyNameCastReqVO companyNameCastReqVO = new CompanyNameCastReqVO();
        companyNameCastReqVO.setCsmCodeList(agentCodeList);
        CommonResult<List<CompanyNameCastRespDTO>> listCommonResult =
                companyInfoApi.companyNameCast(companyNameCastReqVO);
        Map<String, String> cnMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode, CompanyNameCastRespDTO::getCompanyNameLocal,(first, second) -> first));
        Map<String, String> enMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode, CompanyNameCastRespDTO::getCompanyNameEn,(first, second) -> first));
        list.forEach(vo -> {
            vo.setCompanyNameEn(enMap.get(vo.getAgentCode()));
            vo.setCompanyNameLocal(cnMap.get(vo.getAgentCode()));
        });
    }

    /**
     * 批量填充公司名称
     *
     * @param list
     * @param bkpCodeExtractor
     * @param localNameSetter
     * @param enNameSetter
     */
    @Override
    public <T> void fillCompanyNameByBkpCodeFunctionally(List<T> list,
                                                         java.util.function.Function<T, String> bkpCodeExtractor,
                                                         java.util.function.BiConsumer<T, String> localNameSetter,
                                                         java.util.function.BiConsumer<T, String> enNameSetter) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        List<String> bkpCodeList = list.stream()
                .map(bkpCodeExtractor)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (bkpCodeList.isEmpty()) {
            return;
        }

        CompanyNameCastReqVO companyNameCastReqVO = new CompanyNameCastReqVO();
        companyNameCastReqVO.setCsmCodeList(bkpCodeList);
        CommonResult<List<CompanyNameCastRespDTO>> listCommonResult =
            companyInfoApi.companyNameCast(companyNameCastReqVO);

        if (listCommonResult == null || CollectionUtils.isEmpty(listCommonResult.getCheckedData())) {
            return;
        }

        Map<String, String> cnMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(
                    CompanyNameCastRespDTO::getCsmCode,
                    CompanyNameCastRespDTO::getCompanyNameLocal,
                    (first, second) -> first));

        Map<String, String> enMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(
                    CompanyNameCastRespDTO::getCsmCode,
                    CompanyNameCastRespDTO::getCompanyNameEn,
                    (first, second) -> first));

        list.forEach(item -> {
            String bkpCode = bkpCodeExtractor.apply(item);
            if (bkpCode != null) {
                localNameSetter.accept(item, cnMap.get(bkpCode));
                enNameSetter.accept(item, enMap.get(bkpCode));
            }
        });
    }
    /**
     * 批量填充公司名称
     *
     * @param list
     * @param partnerCodeExtractor
     * @param localNameSetter
     * @param enNameSetter
     */
    @Override
    public <T> void fillCompanyNameByPartnerCodeFunctionally(List<T> list,
                                                             java.util.function.Function<T, String> partnerCodeExtractor,
                                                             java.util.function.BiConsumer<T, String> localNameSetter,
                                                             java.util.function.BiConsumer<T, String> enNameSetter) {
        if (CollectionUtils.isEmpty(list)) {
            return;
        }

        List<String> partnerCodeList = list.stream()
                .map(partnerCodeExtractor)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (partnerCodeList.isEmpty()) {
            return;
        }

        PartnerListByCodeReqDTO partnerListByCodeReqDTO = new PartnerListByCodeReqDTO();
        partnerListByCodeReqDTO.setPartnerCodeList(partnerCodeList);
        CommonResult<List<PartnerDataRespDTO>> listCommonResult =
                partnerDataApi.listByCode(partnerListByCodeReqDTO);

        if (listCommonResult == null || CollectionUtils.isEmpty(listCommonResult.getCheckedData())) {
            return;
        }

        Map<String, String> cnMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(
                        PartnerDataRespDTO::getPartnerCode,
                        PartnerDataRespDTO::getPartnerNameCn,
                    (first, second) -> first));

        Map<String, String> enMap = listCommonResult.getCheckedData().stream()
                .collect(Collectors.toMap(
                        PartnerDataRespDTO::getPartnerCode,
                        PartnerDataRespDTO::getPartnerNameEn,
                    (first, second) -> first));

        list.forEach(item -> {
            String partnerCode = partnerCodeExtractor.apply(item);
            if (partnerCode != null) {
                localNameSetter.accept(item, cnMap.get(partnerCode));
                enNameSetter.accept(item, enMap.get(partnerCode));
            }
        });
    }

    @Override
    public void fillVesselName(List<VesselOffHireMaintenanceRespVO> list) {
        List<String> vesselCodes =
            list.stream().map(VesselOffHireMaintenanceRespVO::getVesselCode).collect(Collectors.toList());
        VesselNameListByCodeReqDTO vesselNameReq = new VesselNameListByCodeReqDTO();
        vesselNameReq.setVesselCodeList(vesselCodes);

        CommonResult<List<VesselNameDataRespDTO>> listCommonResult = vesselDataApi.listByCodeList(vesselNameReq);
        Map<String, String> cnMap = listCommonResult.getCheckedData().stream()
            .collect(Collectors.toMap(VesselNameDataRespDTO::getVesselCode, VesselNameDataRespDTO::getVesselNameCn));
        Map<String, String> enMap = listCommonResult.getCheckedData().stream()
            .collect(Collectors.toMap(VesselNameDataRespDTO::getVesselCode, VesselNameDataRespDTO::getVesselNameEn));
        list.forEach(vo -> {
            vo.setVesselNameCn(cnMap.get(vo.getVesselCode()));
            vo.setVesselNameEn(enMap.get(vo.getVesselCode()));
        });
    }

    @Override
    public String getCompanyNameEn(String supplierCode) {
        if (StringUtils.isEmpty(supplierCode)) {
            return null;
        }
        List<String> supplierCodeList = new ArrayList<>();
        supplierCodeList.add(supplierCode);
        Map<String, String> map = getCompanyNameMap(supplierCodeList);
        return map.getOrDefault(supplierCode, null);
    }

    @Override
    public Map<String, String> getCompanyNameMap(List<String> codeList) {
        if (CollectionUtils.isEmpty(codeList)) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        CompanyNameCastReqVO reqVO = new CompanyNameCastReqVO();
        reqVO.setCsmCodeList(codeList);
        CommonResult<List<CompanyNameCastRespDTO>> respList = new CommonResult<>();
        try {
            respList = companyInfoApi.companyNameCast(reqVO);
        } catch (Exception e) {
            log.error("getCompanyNameEn exception", e);
            Assertion.assertTrue(false).raise0(ApiErrorCodeConstants.GET_VENDOR_EN_EXCEPTION.getCode(), e.toString());
        }
        if (CollectionUtils.isEmpty(respList.getData()) || respList.getData().get(0) == null) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        return respList.getData().stream().collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode,
            CompanyNameCastRespDTO::getCompanyNameEn, (oldVal, newVal) -> newVal));
    }

    @Override
    public Map<String, String> getCompanyLocalNameMap(List<String> codeList) {
        if (CollectionUtils.isEmpty(codeList)) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        CompanyNameCastReqVO reqVO = new CompanyNameCastReqVO();
        reqVO.setCsmCodeList(codeList);
        CommonResult<List<CompanyNameCastRespDTO>> respList = new CommonResult<>();
        try {
            respList = companyInfoApi.companyNameCast(reqVO);
        } catch (Exception e) {
            log.error("getCompanyNameEn exception", e);
            Assertion.assertTrue(false).raise0(ApiErrorCodeConstants.GET_VENDOR_EN_EXCEPTION.getCode(), e.toString());
        }
        if (CollectionUtils.isEmpty(respList.getData()) || respList.getData().get(0) == null) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        return respList.getData().stream().collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode,
                CompanyNameCastRespDTO::getCompanyNameLocal, (oldVal, newVal) -> newVal));
    }

    @Override
    public Map<String, CompanyNameCastRespDTO> getCompanyMap(List<String> codeList) {
        if (CollectionUtils.isEmpty(codeList)) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        CompanyNameCastReqVO reqVO = new CompanyNameCastReqVO();
        reqVO.setCsmCodeList(codeList);
        CommonResult<List<CompanyNameCastRespDTO>> respList = new CommonResult<>();
        try {
            respList = companyInfoApi.companyNameCast(reqVO);
        } catch (Exception e) {
            log.error("getCompanyNameEn exception", e);
            Assertion.assertTrue(false).raise0(ApiErrorCodeConstants.GET_VENDOR_EN_EXCEPTION.getCode(), e.toString());
        }
        if (CollectionUtils.isEmpty(respList.getData()) || respList.getData().get(0) == null) {
            return new HashMap<>(CommonConstants.DEFAULT_MAP_COUNT);
        }
        return respList.getData().stream()
            .collect(Collectors.toMap(CompanyNameCastRespDTO::getCsmCode, e -> e, (oldVal, newVal) -> newVal));
    }

    @Override
    public List<CompanyNameCastRespDTO> customerFromCodeList(CompanyNameCastReqVO companyNameCastReqVO) {
        List<CompanyNameCastRespDTO> checkedData = new ArrayList<>();
        CommonResult<List<CompanyNameCastRespDTO>> listCommonResult;
        try {
            listCommonResult = companyInfoApi.companyNameCast(companyNameCastReqVO);
            checkedData = listCommonResult.getCheckedData();
        } catch (Exception e) {
            throw ServiceExceptionUtil.exception(RpcErrorCodeConstants.CUSTOMER_GET_ERROR);
        }
        if (CollectionUtil.isNotEmpty(checkedData)) {
            return checkedData;
        }
        return Collections.emptyList();
    }

}
